
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include "libaxidma.h"

#define AN706_SAMPLENUM (1920)
#define AN706_REGBASE (0x43c00000)

#define POWERDOWN			0
#define RANGE_5V			0
#define	RANGE_10V			1
#define NO_STAND_BY			(1 << 1)
#define	NO_OS				(0 << 2)
#define	OS2					(1 << 2)
#define	OS4					(2 << 2)
#define	OS8					(3 << 2)
#define	OS16				(4 << 2)
#define	OS32				(5 << 2)
#define	OS64				(6 << 2)
#define CHAN1				(0 << 5)
#define CHAN2				(1 << 5)
#define CHAN3				(2 << 5)
#define CHAN4				(3 << 5)
#define CHAN5				(4 << 5)
#define CHAN6				(5 << 5)
#define CHAN7				(6 << 5)
#define CHAN8				(7 << 5)

#define WRITE_CFG		    (1 << 4)
#define READ_CFG			(1 << 5)

//reg operate
int g_iAn706MemFileDev;
void *g_pAn706RegBase;

//axidma operate
axidma_dev_t g_AxiDmaDev;
const array_t *g_apRxChannels;
void *g_pAn706DataBuf;
bool g_waitFlag = true;

void callbackAfterRecive(int channelid, void *data)
{
    (void)(data);

    printf("INFO: callback func triggerd,channelid: %d\n", channelid);
    for (int i = 0; i < AN706_SAMPLENUM; i++)
    {
        printf("%x ", *((unsigned short *)(g_pAn706DataBuf) + i));
    }
    printf("\n");

    g_waitFlag = false;
}

int main()
{
    //init axidma device
    g_AxiDmaDev = axidma_init();
    if (g_AxiDmaDev == NULL)
    {
        printf("Error: can not initialize the AXI DMA device\n");
        return 0;
    }

    //get avaliable rx channels
    g_apRxChannels = axidma_get_dma_rx(g_AxiDmaDev);
    if (g_apRxChannels->len < 1)
    {
        printf("Error: no receive channels found\n");
        return 0;
    }

    //print avaliable channels
    for (int i = 0; i < g_apRxChannels->len; i++)
    {
        printf("INFO: receive channel ID: %d\n", g_apRxChannels->data[i]);
    }

    //mmap the an706 reg base
    g_iAn706MemFileDev = open("/dev/mem", O_RDWR | O_SYNC);
    if (g_iAn706MemFileDev < 0)
    {
        printf("ERROR: can not open /dev/mem\n");
        return 0;
    }
    g_pAn706RegBase = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, g_iAn706MemFileDev, AN706_REGBASE);
    if (!g_pAn706RegBase)
    {
        printf("ERROR: unable to mmap adc registers\n");

        //close an706 memory file dev
        if (g_iAn706MemFileDev)
            close(g_iAn706MemFileDev);

        return 0;
    }

    //start DMA recive
    //per channel data num = 1920 ,per data 16bit,total has 8 adc channel data
    g_pAn706DataBuf = axidma_malloc(g_AxiDmaDev, AN706_SAMPLENUM * 2 * 8);
    printf("the init dma recive buf:\n");
    for (int i = 0; i < AN706_SAMPLENUM; i++)
    {
        printf("%x ", *((unsigned short *)(g_pAn706DataBuf + i)));
    }
    printf("\n");

    printf("preper to start adc\n");
    axidma_stop_transfer(g_AxiDmaDev, g_apRxChannels->data[0]);
    axidma_set_callback(g_AxiDmaDev, g_apRxChannels->data[0], callbackAfterRecive, NULL);
    axidma_oneway_transfer(g_AxiDmaDev, g_apRxChannels->data[0], g_pAn706DataBuf, (AN706_SAMPLENUM) * 2 , false);


    *(volatile unsigned long *)(g_pAn706RegBase + 4) = AN706_SAMPLENUM;
    *(volatile unsigned long *)(g_pAn706RegBase +8) = (
					 NO_STAND_BY | (0<< 2)
							| ((8  - 1) << 5));                  //dut reg
    int  delay = 500;
    while(delay--);
    *(volatile unsigned long *)(g_pAn706RegBase) =  1<<3;                                                       //control ,write dut
    delay = 500;
    while(delay--);
   *(volatile unsigned long *)(g_pAn706RegBase )  =  1;                                                             //start
    delay = 500;
    while(delay--);

    printf("the ADC has start...\n");

    while (g_waitFlag)
        ;

    //close an706 memory file dev
    if (g_iAn706MemFileDev)
        close(g_iAn706MemFileDev);

    //munmap
    munmap(g_pAn706RegBase, MAP_SHARED);

    axidma_destroy(g_AxiDmaDev);

    return 0;
}
